#!/usr/bin/python
#implement forum selection and caching with ttl
#incoporate some unit tests
#reorganize, the logic is horridly hard to follow and convoluted
#optimize program -- when looping, don't check functions if not part of reqs, remove functions from array once found
import urllib2 as u
import re
import BeautifulSoup as bs
import pdb
import json
import argparse
import sys
from StringIO import StringIO

parser = argparse.ArgumentParser()
parser.add_argument('-pages')
parser.add_argument('-name')
parser.add_argument('-level')
parser.add_argument('-quality')
parser.add_argument('-exactmatch',action='store_true')
parser.add_argument('-regex',action='store_true')
parser.add_argument('-all')
parser.add_argument('-fire')
parser.add_argument('-cold')
parser.add_argument('-lightning')
parser.add_argument('-uniquename')
parser.add_argument('-chaos')
parser.add_argument('-hp')
parser.add_argument('-sockets')
parser.add_argument('-links')
args = parser.parse_args()
print args
def compare(val1, val2):
	if val1[0] == '>':
		return True if int(val1[1:]) < val2 else False
	elif val1[0] == '<':
		return True if int(val1[1:]) > val2 else False
	elif val1[0] == '=':
		return True if int(val1[1:]) == val2 else False
	else:
		return True if int(val1) == val2 else False
def nameCompare(val1, val2):
	if args.exactmatch:
		return True if val1.lower() == val2.lower() else False
	elif args.regex:
		reobj = re.compile(val1.lower());
		match = reobj.search(val2.lower())
		return True if match else False
	else:
		return True if val1.lower() in val2.lower() else False
def checkExplicitMod(arg, regex, input):
	if arg != None:
		reobj = re.compile(regex)
		match = reobj.search(input.lower())
		if match:
			result = int(match.group(1))
			if compare(arg, result):
				return 1			
		return -1
	return 0
def checkColdResist(res):
	return checkExplicitMod(args.cold,r"\+([0-9]*?)% to cold resistance",res)
def checkFireResist(res):
	return checkExplicitMod(args.fire,r"\+([0-9]*?)% to fire resistance",res)
def checkLightningResist(res):
	return checkExplicitMod(args.lightning,r"\+([0-9]*?)% to lightning resistance",res)
def checkAllResist(res):
	return checkExplicitMod(args.all,r"\+([0-9]*?)% to all elemental resistances",res)
def checkChaosResist(res):
	return checkExplicitMod(args.chaos,r"\+([0-9]*?)% to chaos resistance",res)
def checkMaxHp(hp):
	return checkExplicitMod(args.hp,r"\+([0-9]*?) to maximum life",hp)
def checkName(name):
	if args.name != None:
		return nameCompare(args.name.lower(),name.lower())
	return True	
def checkUniqueName(name):
	if args.uniquename != None:
			return nameCompare(args.uniquename.lower(),name.lower())
	return True

def checkProperty(arg, regex, input, name):
	if arg != None:
		if input['name'] == name:
			reobj = re.compile(regex)
			match = reobj.search(input['values'][0][0].lower())
			if match:
				result = int(match.group(1))
				if compare(arg, result):
					return 1			
		return -1
	return 0
	#return checkExplicitMod(arg,regex,input)
def checkQuality(qual):
	return checkProperty(args.quality,r"\+([0-9]{1,2}?)%",qual,"Quality")
def checkLevel(lvl):	
	return checkProperty(args.level,r"([0-9]{1,2})",lvl, "Level") #split in case of 20 (max)
#	if args.level != None:
#		return compare(args.level,int(lvl.split(' ')[0]))			
#	return True
def checkSockets(num):
	if args.sockets != None:
		return compare(args.sockets,int(num))			
	return True
	#highest link possible = number of sockets - highest group #
def checkLinks(socks,groups):
	if args.links != None:
		return compare(args.links,socks - groups)
	return True
def parsePages(input):
	if input == None:
		return range(1,2)
	if '-' in input:
		splitted = input.split('-')			
		return range(int(splitted[0]),int(splitted[1])+1)
	else:
		return range(int(input),int(input)+1)
def getJson(text):
	reobj = re.compile(r"\(new R\((.*?)\)\)\.run\(\);")
	match = reobj.search(text)
	if match:
		result = match.group(1)
		return json.load(StringIO(result));
		
	else:
		return None
def checkES(es):
	pass
def checkArmour(arm):
	pass
def checkEvasion(eva):
	pass
def checkPhysDamage(pd):
	pass
mainpage = []
for i in parsePages(args.pages):
		mainpage.extend(bs.BeautifulSoup(u.urlopen("http://www.pathofexile.com/forum/view-forum/415/page/" + str(i)).read()).findAll('div',attrs={'class':'title'}));
results = []		

for i in mainpage:
	url= 'http://www.pathofexile.com' + i.a['href']
	text = u.urlopen(url).read()
	temp = getJson(text)
	if temp != None:
		for j in temp:		
		#	try:				
				print "looking at " + j[1]['typeLine']
				if not checkName(j[1]['typeLine']):
					continue						
				if not checkUniqueName(j[1]['name']):
					continue
				criteriaMatched = True	
				props = []
				if 'explicitMods' not in j[1]:
					j[1]['explicitMods'] = []
				toCheck = [checkLightningResist,checkAllResist,checkFireResist,checkColdResist,checkChaosResist,checkMaxHp]
				modCriteria = [False] * len(toCheck)					
				if 'explicitMods' in j[1] :
					for k in j[1]['explicitMods']: #consider adding all functions to array						
						for index,func in enumerate(toCheck):
							if func(k) > -1: #only remains false if req and not met or not found		
								modCriteria[index] = True #once set to true won't be set to false so doesnt matter that future ones don't match
					#	if checkLightningResist(k) > -1: #if only this cannot check for if it actually had lightning mod, will just remain true the entire time because cannot distinguish between not there and not a req																			
					if False in modCriteria:		
						continue # will only skip if req is not met & not found
			#	print len(j[1]['sockets'])
				if not checkSockets(len(j[1]['sockets'])):				
					continue
				group = 0
				for k in j[1]['sockets']:
					if int(k['group']) > group:
						group = int(k['group'])
				if not checkLinks(len(j[1]['sockets']),group):
					continue
				
				props = [checkQuality, checkLevel]
				propCriteria = [False] * len(props) #fix this shit =_=
				if 'properties' not in j[1]: #fix for rings and stuff that don't have properties; everything has an explicitmod so not needed for above (EXCEPT FOR MAPS)
					j[1]['properties'] = []
					j[1]['properties'].append({"name":"bullshit","values":[[[]]]})
				if 'properties' in j[1]:
					for k in j[1]['properties']:
						for index, func in enumerate(props):
					#		if j[1]['typeLine'] == "Frostbite":
					#					pdb.set_trace()
							if k['values'] != []:
					#			pdb.set_trace()
						#	pdb.set_trace()
								if func(k) > -1: #glitch because it's not checking for correct name =,=
									propCriteria[index] = True

						#			pdb.set_trace()
					if False in propCriteria:
						continue
					if j[1]['typeLine'] == "Decoy Totem":
						pdb.set_trace()
					#	if k['name'] == 'Quality':
					#		if not checkQuality(k['values'][0][0]):
					#			criteriaMatched = False
					#			break											
					#	if k['name'] == 'Level':					
					#		if not checkLevel(k['values'][0][0]):
					#			criteriaMatched = False
					#			break				
					#	props.append(k['name'])
				
			#	if args.level != None and 'Level' not in props:
			#		continue
				#if args.quality != None and 'Quality' not in props:
				#	continue
			#	if not criteriaMatched:
			#		continue											
				print "*" * 20
				print "FOUND ITEM MATCHING CRITERIA"	
				print ((j[1]['name']  + " | ") if j[1]['name'] != "" else "") + j[1]['typeLine']
				print url
				if url not in results:
					results.append(url)
				print "*" * 20

		
print "recap of found pages"
for i in results:
	print i